#ifndef __VOLUME_CTL_INTERNAL_H
#define __VOLUME_CTL_INTERNAL_H

#include "worker.h"
#include "coroutine.h"
#include "volume_proto.h"

#define ENABLE_SNAPSHOT_ROLLBACK_MULTITASK 1
#define SNAPSHOT_ROLLBACK_MULTITASK 10
#define SNAPSHOT_FLAT_MULTITASK 20

typedef struct {
        bmap_t *bmap;
        int bp;
        int bpupdate;
        int curr;
} snapshot_rollback_bp_t;

typedef struct {
        mcache_entry_t *cent;
        uint64_t chunk_idx;

        co_cond_t *cond;
        int *task_count;
        snapshot_rollback_bp_t *snapbp;
        int thin;

        int ret;
} snapshot_rollback_arg_t;

typedef snapshot_rollback_arg_t snapshot_flat_arg_t;

// internals

int __volume_ctl_get(mcache_entry_t **_cent, const chkid_t *chkid);
int __volume_ctl_get__(mcache_entry_t **_cent, const chkid_t *chkid, const fileid_t *parent);

void __volume_ctl_release(mcache_entry_t *cent);

int __volume_ctl_try_load(const chkid_t *chkid, const fileid_t *_parent);
int __volume_ctl_exist(const volid_t *volid);

int __volume_ctl_wrlock(mcache_entry_t *cent);
int __volume_ctl_rdlock(mcache_entry_t *cent);
void __volume_ctl_unlock(mcache_entry_t *cent);

static inline void __snapshot_list_free(struct list_head *list)
{
        struct list_head *pos, *n;

        list_for_each_safe(pos, n, list) {
                list_del(pos);
                yfree((void **)&pos);
        }
}

int rollback_context_init(volume_proto_t *volume_proto);
int rollback_context_destroy(volume_proto_t *volume_proto);
int rollback_context_reload(volume_proto_t *volume_proto);

int rollback_context_dump(volume_proto_t *volume_proto);

#define VOLUME_CTL_BP_INTERVAL 10240
int volume_ctl_getbp(mcache_entry_t *cent, const char *key, uint32_t *bp);
int volume_ctl_setbp(mcache_entry_t *cent, const char *key, uint32_t bp);
int volume_ctl_rmbp(mcache_entry_t *cent, const char *key);

#endif
